#include<sys/socket.h>
#include<sys/epoll.h>

#include "ThreadPool.h"

int exitPipe[2];
void handler(int signum)
{
	printf("signum = %d\n", signum);
	write(exitPipe[1], "1", 1);
}

int main(int argc, const char *argv[])
{
	ARGS_CHECK(argc, 4);

	pipe(exitPipe);
	if (fork()) { // Parent process
		close(exitPipe[0]);
		signal(SIGUSR1, handler);
		wait(NULL);
		printf("Parent is going to exit!\n");
		exit(0);
	}
	close(exitPipe[1]);

	ThreadPool threadpool;
	threadPool_init(&threadpool, atoi(argv[3]));
	_startWorker(&threadpool);
	int sockfd = tcp_init(argv[1], argv[2]);
	ERROR_CHECK(sockfd, -1, "socket create error");

	epollAdd(threadpool.epfd, sockfd);
	epollAdd(threadpool.epfd, exitPipe[0]); // 监听退出管道

	struct epoll_event readyset[1024];
	while (1) {
		int readyNum = epoll_wait(threadpool.epfd, readyset, 1024, -1);
		for (int i = 0; i < readyNum; i++) {
			int currentFd = readyset[i].data.fd;
			if (currentFd == sockfd) {
				// 处理新连接
				int netfd = accept(sockfd, NULL, NULL);
				setNonBlocking(netfd);
				printf("netfd : %d\n", netfd);
				epollAdd(threadpool.epfd, netfd);
				_user_init(&threadpool, netfd);
			} else if (currentFd == exitPipe[0]) {
				// 处理退出信号
				printf("Child is going to exit!\n");
				pthread_mutex_lock(&threadpool._mLock);
				threadpool._exitFlag = 1;
				// 清理未处理的任务
				while (!_taskQueue_is_empty(
					&threadpool._taskQueue)) {
					task_t *task = _taskQueue_front(
						&threadpool._taskQueue);
					_taskQueue_deque(
						&threadpool._taskQueue);
					close(task->_clientFd);
					free(task);
				}
				pthread_cond_broadcast(&threadpool._mCond);
				pthread_mutex_unlock(&threadpool._mLock);
				// 等待所有线程退出
				for (int i = 0;
				     i < threadpool._tidArr._worker_num; ++i) {
					pthread_join(threadpool._tidArr._arr[i],
						     NULL);
				}
				// 关闭资源
				close(sockfd);
				close(threadpool.epfd);
				printf("Child has exited!\n");
				exit(0);
			} else {
				// 处理客户端数据
				int netfd = currentFd;
				train_t cmdTrain;
				memset(&cmdTrain, 0, sizeof(train_t));
				ssize_t ret = recv(netfd, &cmdTrain,
						   sizeof(train_t), 0);
				if (ret <= 0) {
					// 客户端断开或错误
					epollDel(threadpool.epfd, netfd);
					close(netfd);
					continue;
				}
				printf("begin cmd :%d\n", cmdTrain._cmdType);
				printf("begin cmd data = %s\n", cmdTrain._data);
				printf("begin cmd data length = %d\n",
				       cmdTrain._length);
				// 创建任务
				task_t *newTask =
					(task_t *)malloc(sizeof(task_t));
				newTask->_clientFd = netfd;
				newTask->_cmdType = cmdTrain._cmdType;
				newTask->_length = cmdTrain._length;
				strncpy(newTask->_data, cmdTrain._data,
					sizeof(newTask->_data));
				newTask->_data[cmdTrain._length] = '\0';
				// 加入队列
				pthread_mutex_lock(&threadpool._mLock);
				_taskQueue_enque(&threadpool._taskQueue,
						 newTask);
				pthread_cond_broadcast(&threadpool._mCond);
				pthread_mutex_unlock(&threadpool._mLock);
			}
        }
    }
	return 0;
}